using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class AudioManager : MonoBehaviour
{
    public static AudioManager Instance;
    private Transform player;
    [SerializeField] AudioSource sfxSource;
    [SerializeField] private AudioSource bgmSource;
    [SerializeField] private AudioDataBaseSO audioDB;
    [SerializeField] private bool bgmShouldPlay;
    private Coroutine switchBGMCo;
    private string currentBGMGrounpName;
    private AudioClip lastMusicPlayed;
    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;
        DontDestroyOnLoad(gameObject);
    }

    private void Update()
    {
        if (bgmSource.isPlaying == false && bgmShouldPlay)
        {
            if (string.IsNullOrEmpty(currentBGMGrounpName) == false)
            {
                NextBGM(currentBGMGrounpName);
            }
        }
        if (bgmSource.isPlaying && bgmShouldPlay == false)
            StopBGM();
    }
    public void StartBGM(string musicGroup)
    {
        bgmShouldPlay = true;
        if (musicGroup == currentBGMGrounpName)
            return;
        NextBGM(musicGroup);
    }

    public void NextBGM(string musicGroup)
    {
        bgmShouldPlay = true;

        currentBGMGrounpName = musicGroup;

        if (switchBGMCo != null)
            StopCoroutine(switchBGMCo);
        switchBGMCo = StartCoroutine(SwitchMusicCo(musicGroup));
    }
    public void StopBGM()
    {
        bgmShouldPlay = false;
        StartCoroutine(FadeVolumeCo(bgmSource, 0, 1));

        if (switchBGMCo != null)
            StopCoroutine(switchBGMCo);
    }
    private IEnumerator SwitchMusicCo(string musicGroup)
    {
        AudioClipData data = audioDB.Get(musicGroup);
        AudioClip nextMusic = data?.GetAudioClip();

        if (data == null || data.clips.Count == 0)
            yield break;

        if (data.clips.Count > 1)
            while (lastMusicPlayed == nextMusic)
                nextMusic = data.GetAudioClip();

        if (bgmSource.isPlaying)
            yield return FadeVolumeCo(bgmSource, 0, 1f);

        lastMusicPlayed = nextMusic;
        bgmSource.clip = nextMusic;
        bgmSource.volume = 0;
        bgmSource.Play();

        StartCoroutine(FadeVolumeCo(bgmSource, 1f, 1f));
    }

    private IEnumerator FadeVolumeCo(AudioSource bgmSource,float targetVolume,float duration)
    {
        float timer = 0;
        float originalVolume = bgmSource.volume;
        while (timer <= duration)
        {
            timer += Time.deltaTime;

            bgmSource.volume = Mathf.Clamp01(Mathf.Lerp(originalVolume, targetVolume, timer / duration));

            yield return null;
        }
    }

    public void PlaySFX(string soundName, AudioSource sfxSource, float minDistanceToHear)
    {
        var data = audioDB.Get(soundName);

        if (data == null)
            return;
        var clip = data.GetAudioClip();
        if (clip == null)
            return;

        if (player == null)
            player = Player.Instance.transform;

        float distance = Vector2.Distance(sfxSource.transform.position, player.position);
        float t = Mathf.Clamp01(1 - (distance / minDistanceToHear));

        sfxSource.clip = clip;
        sfxSource.volume = Mathf.Lerp(0, data.maxVolume, t);
        sfxSource.pitch = Random.Range(0.9f, 1.1f);
        sfxSource.PlayOneShot(clip);
    }

    public void PlayGlobalSFX(string soundName)
    {
        var data = audioDB.Get(soundName);

        if (data == null)
            return;
        var clip = data.GetAudioClip();
        if (clip == null)
            return;

        sfxSource.clip = clip;
        sfxSource.pitch = Random.Range(0.95f, 1.05f);
        sfxSource.PlayOneShot(clip);
    }
}
